// JScript source code
/*
1. Write a function spellcheck that returns an array. The first element
will be the word to check. The subsequent elements will be the suggestions.
This function should return an array of arrays. The subarrays will contain the word
to check and suggestions. If the subarray contains only one element the word is spelled
correctly or cannot be checked by the engine.

2. Write a function that walks a XML document. It must split the document into
single words. For example it can get the text of an element then the text can be
easily split into an array of words. Each word can be spellchecked, then the correct
word and suggestions can be returned if necessary.
arrWords = eleXML.getText().split() //get the text into an array
for each arrWords
    arrChecked = spellcheck(arrWords[i])
next

OR

Can SAX2 be used and just walk through the document event-wise as suggested:

start document
start element: doc
start element: para
characters: Hello, world!
end element: para
end element: doc
end document


<myxml> 
<p>You really think you are a good speler, don't you?</p> 
</myxml> 


var xmlDocument = new ActiveXObject('Msxml2.DOMDocument.3.0'); 
xmlDocument.loadXML([ 
   '<myxml>', 
   '<p>You really think you are a good speler, don\'t you?</p>', 
   '</myxml>' 
].join('\r\n')); 
xmlDocument.setProperty('SelectionLanguage', 'XPath'); 
var p = xmlDocument.selectSingleNode('myxml/p'); 
var currentChild = p.firstChild; 
var newChild = currentChild.splitText(currentChild.data.indexOf('speler')); 
newChild.splitText('speler'.length); 
var newParent = xmlDocument.createElement('sp'); 
newChild.parentNode.replaceChild(newParent, newChild); 
newParent.appendChild(newChild); 
var sug = xmlDocument.createElement('sug'); 
sug.appendChild(xmlDocument.createTextNode('speller')); 
newParent.appendChild(sug); 


the XML markup (xmlDocument.xml) is now 


<myxml> 
        <p>You really think you are a good <sp>speler<sug>speller</sug></sp>, 
don't you?</p> 
</myxml> 




*/

/*@cc_on @*/
@set @debug = false;


main();

/******************************************************************************
function: getFileList
description: get a list of files from a given folder
input:
    strFolderPath: The path to the folder
output:
    s: a comma separated string containing file names in the folder
******************************************************************************/
function getFiles(strFolderPath)
{
	var objFileSystem;
	var objFolder;
	var objFileCollection;
	var arrFiles = new Array();
	//fc, s;
	objFileSystem = new ActiveXObject("Scripting.FileSystemObject");
	objFolder = objFileSystem.GetFolder(strFolderPath);
	objFilesCollection = new Enumerator(objFolder.files);
	//s = "";
	//for(; !objFileCollection.atEnd(); objFileCollection.moveNext())
	//WScript.Echo("Count: " + objFilesCollection.Count);
	//for(var i = 1; i < objFilesCollection.Count; i++)
	i = 0;
	for(; !objFilesCollection.atEnd(); objFilesCollection.moveNext())
	{
		//s += objFileCollection.item().name + ",";
		arrFiles[i] = objFilesCollection.item().name;
		//WScript.Echo("Item " + i + ": " + objFilesCollection.item().name);
		i++;
	}
	//take care of the comma as the last character
	//s = s.slice(0, s.length - 1);
	return(arrFiles);
}
/******************************************************************************
function: getBibEntry
description: get a single bibliographical entry from a given XML document
input:
    strXmlDoc: the path to the xml document
output:
    getBibEntry: the xml bibliogrpahic entry
******************************************************************************/
function getBibEntry(strXmlDoc)
{
	var strBibEntry;
	var eleIdno;
	var xmlDocIn = new ActiveXObject("Msxml2.DOMDocument.3.0");
	var xmlDocOut = new ActiveXObject("Msxml2.DOMDocument.3.0");
	var strXPath = "//teiHeader/fileDesc/titleStmt/"
	
	xmlDocIn.setProperty("ProhibitDTD", false);
    xmlDocOut.setProperty("ProhibitDTD", false);
    xmlDocIn.resolveExternals = true;
    xmlDocIn.async = false;
    //xmlDocOut.resolveExternals = false;
    xmlDocIn.validateOnParse = true;
	//xmlDocOut.validateOnParse = false;
	xmlDocIn.setProperty("SelectionLanguage", "XPath");
	
	if(!xmlDocIn.load("../xml/" + strXmlDoc))
	{
	    WScript.Echo("Failed to load XML");
	}
	
	if (xmlDocIn.parseError.errorCode != 0) 
	{
		var myErr = xmlDocIn.parseError;
		WScript.Echo("Error:" + myErr.reason);
	} 
	else 
	{
		eleBibEntry = xmlDocOut.createElement("bibl");
		
		//Write the id of the entry
		eleIdno = xmlDocOut.createElement("idno");
		eleIdno.text = strXmlDoc;
		eleBibEntry.appendChild(eleIdno);
		
		/*Debug*/
		//WScript.Echo(eleBibEntry.xml);

		//write the title of the document
		//WScript.Echo(xmlDocIn.xml);
		objNodeList = getNodeList(xmlDocIn, strXPath + "title");
		appendNodeList(eleBibEntry, objNodeList);

		//write the author of the document
		objNodeList = getNodeList(xmlDocIn, strXPath + "author");
		appendNodeList(eleBibEntry, objNodeList);

		//write the editor of the document
		objNodeList = getNodeList(xmlDocIn, strXPath + "editor");
		appendNodeList(eleBibEntry, objNodeList);

		
		/*Debug*/
		//WScript.Echo(eleBibEntry.xml);
		return eleBibEntry;
	}
}
/******************************************************************************
function: appendNodeList
description: Append a node list to an element
input:
    eleXML: A XML element.
    nodList: A node list.
output:
    eleXML: The resulting XML element.
******************************************************************************/
function appendNodeList(eleXML, nodeList)
{
    for (var i = 0; i < nodeList.length; i++)
	{
		eleXML.appendChild(nodeList.item(i));
	}
	return(eleXML);
}
/******************************************************************************
function: getNodeList
description: Get a list of nodes from the given XML document.
input:
    xmlDoc: A XML document object
    strXPath: A XPath string to select from the document.
output:
    objNodeList: A list of nodes selected.
******************************************************************************/
function getNodeList(xmlDoc, strXPath)
{
    var objNodeList;
    objNodeList = xmlDoc.documentElement.selectNodes(strXPath);
    return objNodeList;
}
/******************************************************************************
function: getNode
description: Get a nodes from the given XML document.
input:
    xmlDoc: A XML document object
    strXPath: A XPath string to select from the document.
output:
    objNode: A node 
******************************************************************************/
function getNode(xmlDoc, strXPath)
{
    var objNode;
    objNode = xmlDoc.documentElement.selectSingleNode(strXPath);
    return objNode;
}
/******************************************************************************
function: getTEIDocument
description: Create a TEI document to work with
input:
    xmlDoc: an XML document object.
output: a minimal TEI document.
    getTEIDocument: The TEI document
******************************************************************************/
function getTEIDocument(xmlDoc, strStyleSheet)
{
    //title
	eleTitle = xmlDoc.createElement("title");
	
	//author
	eleAuthor = xmlDoc.createElement("author");
	
	//title statement
	eleTitleStmt = xmlDoc.createElement("titleStmt");
	eleTitleStmt.appendChild(eleTitle);
	eleTitleStmt.appendChild(eleAuthor);
	
	//just a paragraph
	eleP = xmlDoc.createElement("p");
	
	//publication statment
	elePublicationStmt = xmlDoc.createElement("publicationStmt");
	elePublicationStmt.appendChild(eleP);
	
	/*Debug*/
	//WScript.Echo(elePublicationStmt.xml);
	
	//just a(nother) paragraph
	/*Why recreate this--why doesn't it work if I don't*/
	eleP = xmlDoc.createElement("p");
	
	//source description
	eleSourceDesc = xmlDoc.createElement("sourceDesc");
	eleSourceDesc.appendChild(eleP);
	
	//compose the header element
	
	//file description
	eleFileDesc = xmlDoc.createElement("fileDesc");
	eleFileDesc.appendChild(eleTitleStmt);
	eleFileDesc.appendChild(elePublicationStmt);
	eleFileDesc.appendChild(eleSourceDesc);
	
	//teiHeader
	eleTeiHeader = xmlDoc.createElement("teiHeader")
	eleTeiHeader.appendChild(eleFileDesc);

	//make the body of the document
	
	//div
	eleDiv = xmlDoc.createElement("div");
	eleP = xmlDoc.createElement("p");
	eleDiv.appendChild(eleP);
	
	//body
	eleBody = xmlDoc.createElement("body");
	eleBody.appendChild(eleDiv);
	
	//text
	eleText = xmlDoc.createElement("text");
	eleText.appendChild(eleBody);
	
	//TEI.2
	eleTEI2 = xmlDoc.createElement("TEI.2");
	eleTEI2.appendChild(eleTeiHeader);
	eleTEI2.appendChild(eleText);
	
	/*Debug*/
	//WScript.Echo(eleTEI2.xml);
	//xmlDocOut.async = false

	pi = xmlDoc.createProcessingInstruction("xml", "version=\"1.0\" encoding=\"UTF-8\"");
	bResult = xmlDoc.loadXML(pi.xml
	    + strStyleSheet
	    + '<!DOCTYPE TEI.2 PUBLIC "-//TEI P4//DTD Main Document Type//EN" "http://www.tei-c.org/Lite/DTD/teixlite.dtd">'
		+ eleTEI2.xml);
	if(!bResult)
	{
	    WScript.Echo("Error Loading xmlDocOut: " + xmlDoc.parseError.reason);
	}
	/*Debug*/
	//WScript.Echo(xmlDoc.xml);
	//xmlDocOut.save(strFileName);
	return(xmlDoc);
}
/******************************************************************************
function: main
description: The main function of program.
input:
    
output:
    
******************************************************************************/
function main()
{
    //createBibliography();
    //xmlSpellcheck("../xml/00000001.xml");
    teiLibrarySpellcheck();
 /*  
    var objWord = new ActiveXObject("Word.Application");
    var objDoc = objWord.Documents.Add();
    arrWords = spellcheck("thank", objWord);
    WScript.Echo("arrWords.length: " + arrWords.length);
    @if(@debug == true)
    {
        for(var i = 0; i < arrWords.length; i++)
        {
            WScript.Echo("main() " + arrWords[i]);
        }
    }
    @end
    
    for(var i = 0; i < arrWords.length; i++)
    {
        WScript.Echo(arrWords[i]);
    }
    objWord.Quit();
*/
}
/******************************************************************************
function: createBibliography
description: Create a bibliography from a set of XML documents in TEI format
input:
    
output:
    
******************************************************************************/
function createBibliography()
{
	var arrFiles//, strBibList, strTitleStmt, strPublicationStmt, strTEIBody, strTEIDocument, strFileName;
	var xmlDocOut = new ActiveXObject("Msxml2.DOMDocument.3.0");
	xmlDocOut.resolveExternals = true;
	xmlDocOut.validateOnParse = false;
	xmlDocOut.async = false;
	var strXPath = "//teiHeader/fileDesc/titleStmt/"

	arrFiles = getFiles("../xml"); //fileList("../xml").split(",");
	
	//set the output file name and path
	strFileName = "X:\\manifest.xml";
	
	//Create the bibllogrpahy list
	eleListBibl = xmlDocOut.createElement("listBibl");
	
	//iterate through the array
	for(i = 0; i < arrFiles.length; i++)
	{
		WScript.Echo("Processing item " + (i + 1) + " of " + arrFiles.length);
		//WScript.Echo("Array Item: " + arrFiles[i]);
		eleListBibl.appendChild(getBibEntry(arrFiles[i]));
	}
	
	//Create a TEI complaint XML document
	strStyleSheet = '<?xml-stylesheet href="manifest.xsl" type="text/XSL"?>'
	xmlDocOut = getTEIDocument(xmlDocOut, strStyleSheet);
	
	//title
	objNode = getNode(xmlDocOut, strXPath + "title");
    objNode.text = "Manifest";
	
	//author
	objNode = getNode(xmlDocOut, strXPath + "author");
    objNode.text = "Jeremy Porter";
    
    //div
    objNode = getNode(xmlDocOut, "//text/body/div");
    objNode.appendChild(eleListBibl);

	xmlDocOut.save(strFileName);
}
/******************************************************************************
function: xmlSpellcheck
description: Check the spelling of an entire XML document.
input:
    An XML document to check.
output:
    A checked XML document to save to disk.
******************************************************************************/
function xmlSpellcheck(strXMLDoc)
{
    var xmlDoc = new ActiveXObject("Msxml2.DOMDocument.3.0");
    var comment;
    var root;
    var arrText;
    var arrWords;
    var eleSpellList;
    var eleItem;
    xmlDoc.async = false;
    xmlDoc.load(strXMLDoc);//"../xml/00000001.xml");
    if (xmlDoc.parseError.errorCode != 0)
    {
       var myErr = xmlDoc.parseError;
       WScript.Echo("Error: " + myErr.reason);
    }
    else
    {
        //create word object and add document
        var objWord = new ActiveXObject("Word.Application");
        var objDoc = objWord.Documents.Add();
        
        eleList = xmlDoc.createElement("list");
        
        root = xmlDoc.documentElement;
        for (var i=0; i<root.childNodes.length; i++)
        {
            //WScript.Echo(i);
            comment = root.childNodes.item(i);
            //WScript.Echo(comment.text);
            arrText = comment.text.split(" ");
            for(var j=0; j<arrText.length; j++)
            {
                arrWords = spellcheck(arrText[j], objWord);
                
                //eleList = xmlDoc.createElement("list");
                for(var k=0; k<arrWords.length; k++)
                {
                    
                    eleItem = xmlDoc.createElement("item");
                    eleItem.text = arrWords[k];
                    attType = xmlDoc.createAttribute("rend");
                    
                    if(k==0)
                    {
                        attType.value = "suspect";
                    }
                    else
                    {
                        attType.value = "suggestion";
                    }
                    eleItem.attributes.setNamedItem(attType);
                    eleList.appendChild(eleItem);
                    
                    /*
                    eleItem = xmlDoc.createElement("item");
                    eleItem.text = arrWords[k];
                    eleList.appendChild(eleItem);
                    
                    eleMainItem = xmlDoc.createElement("item");
                    eleMainItem.appendChild(eleList);
                    eleMainList.appendChild(eleMainItem);*/
                }
            }
        }
        objWord.Quit();
    }

    @if(@debug)
    {
        WScript.Echo("xmlSpellcheck: " + eleList.xml);
    }
    @end
    return(eleList);
}
/******************************************************************************
function: teiLibrarySpellcheck
description: spellcheck all the documents in a library and output a spellcheck
document in TEI compliant form.
input:
    
output:
    
******************************************************************************/
function teiLibrarySpellcheck()
{
    var xmlDoc = new ActiveXObject("Msxml2.DOMDocument.3.0");
    xmlDoc.resolveExternals = true;
	xmlDoc.validateOnParse = false;
	xmlDoc.async = false;
	
	/*
    var xmlDocOut = new ActiveXObject("Msxml2.DOMDocument.3.0");
	xmlDocOut.resolveExternals = true;
	xmlDocOut.validateOnParse = false;
	xmlDocOut.async = false;
    */
    //get the files in the library
    arrFiles = getFiles("../xml");
    
    //get a TEI document
    xmlDoc = getTEIDocument(xmlDoc, "");
    
    //get the div element
    objNode = getNode(xmlDoc, "//text/body/div");
    
    //create a list element
    eleList2 = xmlDoc.createElement("list");
    
    //spell check each document
    //for(i = 0; i < arrFiles.length; i++)
    for(var i = 0; i < 1; i++)
    {
        //What document is being processed
        WScript.Echo("Processing document: " + arrFiles[i]);
        
        //get the eleSpellList from each document
        eleSpellList = xmlSpellcheck("../xml/" + arrFiles[i]);
        
        //append the eleItem to eleList
        eleItem = xmlDoc.createElement("item");
        attID = xmlDoc.createAttribute("id");
        attID.value = "sp" + arrFiles[i];
        eleItem.attributes.setNamedItem(attID);
        eleItem.appendChild(eleSpellList);
        
        //append the eleItem to the eleList for persistence
        eleList2.appendChild(eleItem);
    }
    
    //append the eleList to the div element
    objNode.appendChild(eleList2);
    
    //save the document
    xmlDoc.save("x:\\spellcheck.xml");
    
}
/******************************************************************************
function: spellcheck
description: Check the spelling of a single word and return the word and it's
suggested spellings.
input:
    strWord: A string to spell check
    objWord: An ActiveXObject for the Microsoft Word application.
output:
    arrWords: An array of strings. The first element is the word to check.
    Subsequent elements are the suggestions, if necessary.
******************************************************************************/
function spellcheck(strWord, objWord)
{
    var arrWords = new Array();

    if(!objWord.CheckSpelling(strWord))
    {
        arrWords[0] = strWord;
        colSuggestions = objWord.GetSpellingSuggestions(strWord);
        
        for(i = 1; i <= colSuggestions.count; i++)
        {
            arrWords[i] = colSuggestions.item(i);
        }
    }
    @if(@debug == true)
    {
        for(var i = 0; i < arrWords.length; i++)
        {
            WScript.Echo("spellcheck: " + arrWords[i]);
        }
    }
    @end
    return arrWords;
}